#include"Operation.hpp"
#include"Operand.hpp"
#include"Region.hpp"
#include"MachineSpec.hpp"


Instruction * Instruction_cast(Node * n)
{
	if(n->get_type_flag() &(START_NODE | END_NODE))
		return NULL;
	else
		return ( Instruction* )n;
}


#define CAST_TEMPLATE(ID, CAST_NAME)\
Operation<ID> * CAST_NAME(Node *n) \
{	\
	if(n->get_type_flag() & ID) \
		return (Operation<ID>*) n; \
	else \
		return NULL; \
}

CAST_TEMPLATE(SIMD_MATH, SIMDMath_cast)

CAST_TEMPLATE(SIMD_LOAD, SIMDLoad_cast)

CAST_TEMPLATE(SIMD_STORE, SIMDStore_cast)

CAST_TEMPLATE(LOAD, Load_cast)

CAST_TEMPLATE(STORE, Store_cast)

CAST_TEMPLATE(NORMAL_OPER, Normal_cast)

CAST_TEMPLATE(JSR, Jsr_cast)

CAST_TEMPLATE(JSR_SR, Jsr_sr_cast)

CAST_TEMPLATE(DATA_ADDR, DATA_ADDR_cast)

CAST_TEMPLATE(ADDR_DATA, ADDR_DATA_cast)

CAST_TEMPLATE(RTS, Rts_cast)

CAST_TEMPLATE(DATA_SR, DATA_SR_cast)

CAST_TEMPLATE(BR_OPER, Branch_cast)

CAST_TEMPLATE(START_NODE, StartNode_cast)
CAST_TEMPLATE(END_NODE, EndNode_cast);


/*
 * START_NODE, END_NODE
 */


void Instruction::registe_resource(enum _Function_Type ft, int time, UsageFU * fu)
{
	
}


Operation<START_NODE>::Operation(const std::vector<int> & live_in): Node(START_NODE)
{
	for(int i = 0; i < live_in.size(); i++)
	{
		if(M_is_macro_id(live_in[i] ))
			implict_dest[i] = new MacroValue((enum MACRO_ID)live_in[i]);
		else
			implict_dest[i] = new GenValue(live_in[i]);
	}
}
Operation<END_NODE>::Operation(const std::vector<int> & live_out): Node(END_NODE)
{
	for(int i = 0; i < live_out.size(); i++)
	{
		if(M_is_macro_id(live_out[i]))
			implict_src[i] = new MacroValue((enum MACRO_ID) live_out[i]);
		else
			implict_src[i] = new GenValue(live_out[i]);
	}
}


/*
 * the constructor member function
 */

Operation<SPILL | STORE>::Operation<SPILL|STORE>(int spill_offset, int id): Instruction(STORE|SPILL)
{
	RegValue * src0 = new MacroValue(SPILL_SP);
	src.push_back(src0);
	ImmValue *src1 = new ImmValue(spill_offset);
	src.push_back(src1);
	RegValue * src2 = new GenValue(id,NO_CORE);
	src.push_back(src2);
	src_opd[0] = new AddrOperand(src0);
	src_opd[1] = new AddrOperand(src1);
	src_opd[2] = new DataOperand(src2);
}


Operation<SPILL | LOAD>::Operation(int spill_offset, int id): Instruction(LOAD|SPILL)
{
	Value *dest0 = new GenValue(id, NO_CORE);
	Value *src0 = new MacroValue(SPILL_SP);
	Value *src1 = new ImmValue(spill_offset);
	src.push_back(src0);
	src.push_back(src1);
	dest.push_back(dest0);
	dest_opd[0] = new DataOperand(dest0);	
	src_opd[0] = new AddrOperand(src0);	
	src_opd[1] = new AddrOperand(src1);
}

/*
 *================================
 *  	SIMD_MATH
 *================================
 */


/*
 *================================
 *  	SIMD_LOAD
 *================================
 */

/*
 * ===============================
 * 	SIMD_STORE
 * ===============================
 */

/*================================
 * 	BR_OPER
 *==============================
 */

void Operation<BR_OPER>::build_implict_value(const std::vector<int>& ids)
{
	RegValue * v = NULL;
	for(int i = 0; i < ids.size(); i++)
	{
		if(M_is_macro_id(ids[i]))
		{
			v = new MacroValue((enum MACRO_ID) ids[i]);
		}	
		else
		{
			v = new GenValue(ids[i]);
		}
		implict_src.push_back(v);
	}	
}

